/*
  gconn.h
  Description: Connection Pool for GIGI
  Created: 2009.10.19
  Version: 1.0
*/

#ifndef __GCONN_H__
#define __GCONN_H__

#include "gutil.h"

#ifdef __cplusplus
extern "C" {
#endif

#define PEER_SOCKET_CACHE           64
#define NODE_HASH_COUNT             37
#define CONNECT_TIMEOUT             10000
#define SHAKEHAND_TIMEOUT           20000
#define GIGI_TASK_CACHE_SIZE        128

#define SHAKEHAND_CMD_CLOSE         0x03087819
#define SHAKEHAND_CMD_REUSE         0x12237919
#define SHAKEHAND_CMD_CONNECT       0x03270920

#define EVENT_INIT_COUNT            4
#define SELECT_TIMEOUT              3
#define IDLE_INTERNAL               30000000  //3s

#ifdef WINDOWS
  #define DEF_MAX_COUNT_OF_POOL 50
#else
  #define DEF_MAX_COUNT_OF_POOL 800
#endif

// condi object based socket pair
// 
typedef struct gigi_event_t
{
  struct gigi_event_t* _next;
  FD_SOCKET            _in;
  FD_SOCKET            _out;
}gigi_event;

// fd_pool
//
typedef struct fd_pool_t
{
  struct fd_pool_t* _next;
  struct fd_pool_t* _prev;
  int               _ref_count;
  GIGIONE           _context;
  GIGI_ID           _node_id;
  int               _pool_count;
  GIGI_SOCKET       _socket_pool; 
  GIGI_SOCKET       _peer_socket;
  int               _active_peer_socket_order;
}fd_pool;


// accept Event struct
//
typedef struct acceptEvent_t
{
  struct acceptEvent_t* _next;
  struct acceptEvent_t* _prev;
  gigi_event*           _event;
  GIGI_SOCKET           _result;
}acceptEvent;

// callback
//
typedef struct gigi_callback_info_t
{
  struct gigi_callback_info_t* _next;
  struct gigi_callback_info_t* _prev;
  GIGIONE                      _context;
  GIGI_CALLBACK                _func;
  void *                        _ctx;
}gigi_callback_info;

typedef struct gmpi_func_list_t
{
  struct gmpi_func_list_t * _next;
  struct gmpi_func_list_t * _prev;
  GMPI_FUNC_DEF             _funcs;
}gmpi_func_list;


// service
//
typedef struct gigi_service_context_t
{
  GIGI_SERVICE       _next;
  GIGI_SERVICE       _prev;
  GIGIONE            _context;
  
  GIGI_ID            _service_id;
  ring_root          _wait_list;
  GIGI_SOCKET        _accept_list;
  int                _accept_list_count;
  int                _accept_list_max;
  GIGI_SERVICE_FUNC  _func;
  void *              _func_ctx;
}gigi_service_context;

// gigi context
//
typedef struct gigi_context_t
{
  GIGI_ID             _my_node_id;
  MUTEX_T             _lock;

  // nodehash 
  // 
  ring_root           _fd_pool_hash[NODE_HASH_COUNT];
  int                 _cfg_pool_max;
  int                 _conn_max_count;
  int                 _conn_count;
  int                 _conn_expried_time;
  int                 _idle_count;
  ring_root           _service_list;

  //
  FD_SOCKET           _my_fd;
  gigi_event*         _mgr_event;
  int                 _gigi_port;
  unsigned short      _last_service_id;   // unsed to generate the service id
  GIGI_SERVICE        _gigi_service;

  // other resource 
  gigi_event*         _evt_pool;
  GIGI_SOCKET         _peer_cache[PEER_SOCKET_CACHE];

#ifdef GIGI_DEBUG
  int                 _cacheHit;
  int                 _cacheMissing;
#endif
  
  //
  ring_root           _callback_list;

  THREAD_T            _thread;
  int                 _is_run;

  // task
   ring_root          _func_list_root;
   GMPI_FUNC_DEF      _func_cache[GIGI_TASK_CACHE_SIZE];
#ifdef GIGI_DEBUG
   int                _func_cache_hit;
   int                _func_cache_missed;
#endif

}gigi_context;

// GIGI socket struct
//
typedef struct gigi_socket_context_t
{
  struct gigi_socket_context_t * _next;
  fd_pool*            _node_pool;
  struct fd_stream_t  _tcp_fd;
  GIGI_ID             _service_id;
  int                 _order;
  int                 _last_used_time;
  char                _created;
  char                _error;
  char                _raw_mode;
}gigi_socket_context;

//
//
#define GIGI_HANDLE_CHECK(Err)                \
  do { if ( context == NULL )                      \
  { extern GIGIONE gigi_global_context;            \
    context = gigi_global_context;                      \
    if ( context == NULL ) { return Err; } } } while(0)

#define _gigi_event_wait(p, tm) \
  do { char cmd=0; fd_recv (p->_out, &cmd, (int)sizeof (cmd), tm); \
  } while (0)

#define _gigi_event_set(p) \
  do { char cmd=0; send (p->_in, &cmd, (int)sizeof (cmd), 0);  \
  } while (0)

int _socket_list_del (GIGI_SOCKET * root, GIGI_SOCKET fd);

#ifdef __cplusplus
}
#endif

#endif


